package DEEPERsource.DEEPERsource.source.jung.entities;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import edu.uci.ics.jung.graph.DirectedEdge;
import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.impl.DirectedSparseEdge;
import edu.uci.ics.jung.utils.UserData;
import graph.Keys;

public class NewPath {

	public Vertex[] vertices;
	public DirectedEdge[] edges;
	//allowed marks:
	//top, bottom, inner
	public String[] vMarks;
	//in, out w.r.t. 'left' vertex
	public String[] eMarks;
	public int length = 0;
	
	public NewPath(int vertAmount){
		vertices = new Vertex[vertAmount];
		edges = new DirectedEdge[vertAmount-1];
		vMarks = new String[vertAmount];
		eMarks = new String[vertAmount-1];
		length = vertAmount;
	}
	
	public String toString(){
		StringBuffer sb = new StringBuffer("");
		for(int i = 0; i<length-1; i++){
			sb.append(vertices[i].getUserDatum(Keys.LABEL));
			if(eMarks[i].equals("in")){
				sb.append("<-");
				sb.append(edges[i].getUserDatum(Keys.LABEL));
				sb.append("-");
			}else{
				sb.append("-");
				sb.append(edges[i].getUserDatum(Keys.LABEL));
				sb.append("->");
			}			
		}
		sb.append(vertices[length-1].getUserDatum(Keys.LABEL));
		return sb.toString();
	}
	
	public Vertex[] getRoots(){
		List<Vertex> tops = new ArrayList<Vertex>();
		for(int i = 1; i<length-2;i++){
			if(vMarks[i].equals("top")){
				tops.add(vertices[i]);
			}
		}
		return tops.toArray(new Vertex[tops.size()]);
	}
	
	public String serialize() {
		StringBuffer sb = new StringBuffer();
		sb.append("\nLENGTH\n");
		sb.append(length);
		sb.append("\n");
		sb.append("\nVERTICES\n");
		for (Vertex v : vertices) {
			sb.append(v.getClass().getCanonicalName());
			sb.append("\t");
			sb.append(v.getUserDatum(Keys.INDEX));
			sb.append("\t");
			sb.append(v.getUserDatum(Keys.LABEL));
			sb.append("\t");
			sb.append(v.getUserDatum(Keys.POS));
			sb.append("\t");
			sb.append("\n");
		}
		sb.append("\nEDGES\n");
		for(DirectedEdge e : edges){
			sb.append(e.getSource().getUserDatum(Keys.INDEX));
			sb.append("\t");
			sb.append(e.getDest().getUserDatum(Keys.INDEX));
			sb.append("\t");
			sb.append(e.getUserDatum(Keys.INDEX));
			sb.append("\t");
			sb.append(e.getUserDatum(Keys.LABEL));
			sb.append("\n");
		}
		sb.append("\nVMARKS\n");
		for(String str : vMarks){
			sb.append(str);
			sb.append("\n");
		}
		sb.append("\nEMARKS\n");
		for(String str : eMarks){
			sb.append(str);
			sb.append("\n");
		}
		return sb.toString();
	}

	public static NewPath deserialize(BufferedReader stream) throws IOException {
		String s;
		NewPath path = null;
		Graph g = new Graph();
		boolean vertices = false;
		boolean edges = false;
		boolean vMarks = false;
		boolean eMarks = false;
		boolean length = false;
		int i = 0;
		while ((s = stream.readLine()) != null) {
			if(s.equals("")){
				continue;
			}
			if (s.equals("EDGES")) {
				edges = true;
				vertices = false;
				vMarks = false;
				eMarks = false;
				length = false;
				i = 0;
				continue;
			}else if(s.equals("VERTICES")){
				edges = false;
				vertices = true;
				vMarks = false;
				eMarks = false;
				length = false;
				i = 0;
				continue;
			}else if(s.equals("VMARKS")){
				edges = false;
				vertices = false;
				vMarks = true;
				eMarks = false;
				length = false;
				i = 0;
				continue;
			}else if(s.equals("EMARKS")){
				edges = false;
				vertices = false;
				vMarks = false;
				eMarks = true;
				length = false;
				i = 0;
				continue;
			}else if(s.equals("LENGTH")){
				edges = false;
				vertices = false;
				vMarks = false;
				eMarks = false;
				length = true;
				i = 0;
				continue;
			}
			
			String[] split = s.split("\t");
			if (length) {
				path = new NewPath(Integer.parseInt(split[0]));
			}else if (vertices) {
				Vertex v;
				try {
					v = (Vertex) Class.forName(split[0]).newInstance();
				} catch (Exception e) {
					e.printStackTrace();
					return null;
				}
				v.setUserDatum(Keys.INDEX, split[1], UserData.SHARED);
				v.setUserDatum(Keys.LABEL, split[2], UserData.SHARED);
				v.setUserDatum(Keys.POS, split[3], UserData.SHARED);
				path.vertices[i++] = v;
				g.addVertex(v);
			} else if(edges){
				Vertex v1 = g.findVertex(Integer.parseInt(split[0]));
				Vertex v2 = g.findVertex(Integer.parseInt(split[1]));
				DirectedEdge e = new DirectedSparseEdge(v1, v2);
				e.setUserDatum(Keys.INDEX, split[2], UserData.SHARED);
				e.setUserDatum(Keys.LABEL, split[3], UserData.SHARED);
				g.addEdge(e);
				path.edges[i++] = e;
			} else if(vMarks){
				path.vMarks[i++] = split[0];
			}else if(eMarks){
				path.eMarks[i++]= split[0];
			}
		}
		return path;
	}

}
